home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic 4 Database How-To / Visual Basic 4 Database - How-to (The Waite Group)(1995).iso / isam3.fr_ / isam3.fr
Text File  |  1995-07-05  |  39KB  |  1,229 lines

  1. VERSION 4.00
  2. Begin VB.Form frmCustomers 
  3.    BackColor       =   &H00C0C0C0&
  4.    BorderStyle     =   3  'Fixed Dialog
  5.    Caption         =   "Customers"
  6.    ClientHeight    =   3870
  7.    ClientLeft      =   1710
  8.    ClientTop       =   1995
  9.    ClientWidth     =   8205
  10.    BeginProperty Font 
  11.       name            =   "MS Sans Serif"
  12.       charset         =   0
  13.       weight          =   700
  14.       size            =   8.25
  15.       underline       =   0   'False
  16.       italic          =   0   'False
  17.       strikethrough   =   0   'False
  18.    EndProperty
  19.    Height          =   4560
  20.    Left            =   1650
  21.    LinkTopic       =   "Form1"
  22.    MaxButton       =   0   'False
  23.    ScaleHeight     =   3870
  24.    ScaleWidth      =   8205
  25.    Top             =   1365
  26.    Width           =   8325
  27.    Begin VB.CommandButton cmdClose 
  28.       Caption         =   "Cl&ose"
  29.       Height          =   315
  30.       Left            =   6720
  31.       TabIndex        =   26
  32.       Top             =   3300
  33.       Width           =   1095
  34.    End
  35.    Begin VB.CommandButton cmdMove 
  36.       Caption         =   ">>"
  37.       BeginProperty Font 
  38.          name            =   "MS Sans Serif"
  39.          charset         =   0
  40.          weight          =   700
  41.          size            =   9.75
  42.          underline       =   0   'False
  43.          italic          =   0   'False
  44.          strikethrough   =   0   'False
  45.       EndProperty
  46.       Height          =   315
  47.       Index           =   3
  48.       Left            =   2400
  49.       TabIndex        =   25
  50.       Top             =   3300
  51.       Width           =   495
  52.    End
  53.    Begin VB.CommandButton cmdMove 
  54.       Caption         =   ">"
  55.       Default         =   -1  'True
  56.       BeginProperty Font 
  57.          name            =   "MS Sans Serif"
  58.          charset         =   0
  59.          weight          =   700
  60.          size            =   9.75
  61.          underline       =   0   'False
  62.          italic          =   0   'False
  63.          strikethrough   =   0   'False
  64.       EndProperty
  65.       Height          =   315
  66.       Index           =   2
  67.       Left            =   1920
  68.       TabIndex        =   24
  69.       Top             =   3300
  70.       Width           =   495
  71.    End
  72.    Begin VB.CommandButton cmdMove 
  73.       Caption         =   "<"
  74.       BeginProperty Font 
  75.          name            =   "MS Sans Serif"
  76.          charset         =   0
  77.          weight          =   700
  78.          size            =   9.75
  79.          underline       =   0   'False
  80.          italic          =   0   'False
  81.          strikethrough   =   0   'False
  82.       EndProperty
  83.       Height          =   315
  84.       Index           =   1
  85.       Left            =   1380
  86.       TabIndex        =   23
  87.       Top             =   3300
  88.       Width           =   555
  89.    End
  90.    Begin VB.CommandButton cmdMove 
  91.       Caption         =   "<<"
  92.       BeginProperty Font 
  93.          name            =   "MS Sans Serif"
  94.          charset         =   0
  95.          weight          =   700
  96.          size            =   9.75
  97.          underline       =   0   'False
  98.          italic          =   0   'False
  99.          strikethrough   =   0   'False
  100.       EndProperty
  101.       Height          =   315
  102.       Index           =   0
  103.       Left            =   900
  104.       TabIndex        =   22
  105.       Top             =   3300
  106.       Width           =   495
  107.    End
  108.    Begin VB.CommandButton cmdDelete 
  109.       Caption         =   "&Delete "
  110.       Height          =   315
  111.       Left            =   5400
  112.       TabIndex        =   21
  113.       Top             =   3300
  114.       Width           =   1095
  115.    End
  116.    Begin VB.TextBox txtData 
  117.       Alignment       =   2  'Center
  118.       DataField       =   "STATE"
  119.       DataSource      =   "Data1"
  120.       Height          =   315
  121.       Index           =   6
  122.       Left            =   4800
  123.       MaxLength       =   2
  124.       TabIndex        =   13
  125.       Top             =   2100
  126.       Width           =   405
  127.    End
  128.    Begin VB.TextBox txtData 
  129.       DataField       =   "ZIP"
  130.       DataSource      =   "Data1"
  131.       Height          =   315
  132.       Index           =   7
  133.       Left            =   6360
  134.       MaxLength       =   10
  135.       TabIndex        =   15
  136.       Top             =   2100
  137.       Width           =   1215
  138.    End
  139.    Begin VB.TextBox txtData 
  140.       DataField       =   "PHONE"
  141.       DataSource      =   "Data1"
  142.       Height          =   315
  143.       Index           =   8
  144.       Left            =   1380
  145.       MaxLength       =   14
  146.       TabIndex        =   17
  147.       Top             =   2580
  148.       Width           =   1455
  149.    End
  150.    Begin VB.TextBox txtData 
  151.       DataField       =   "FAX"
  152.       DataSource      =   "Data1"
  153.       Height          =   315
  154.       Index           =   9
  155.       Left            =   3960
  156.       MaxLength       =   14
  157.       TabIndex        =   19
  158.       Top             =   2580
  159.       Width           =   1455
  160.    End
  161.    Begin VB.CommandButton cmdAdd 
  162.       Caption         =   "&Add"
  163.       Height          =   315
  164.       Left            =   4080
  165.       TabIndex        =   20
  166.       Top             =   3300
  167.       Width           =   1095
  168.    End
  169.    Begin VB.TextBox txtData 
  170.       DataField       =   "CITY"
  171.       DataSource      =   "Data1"
  172.       Height          =   315
  173.       Index           =   5
  174.       Left            =   1380
  175.       MaxLength       =   20
  176.       TabIndex        =   11
  177.       Top             =   2100
  178.       Width           =   2595
  179.    End
  180.    Begin VB.TextBox txtData 
  181.       DataField       =   "ADDRESS2"
  182.       DataSource      =   "Data1"
  183.       Height          =   315
  184.       Index           =   4
  185.       Left            =   1380
  186.       MaxLength       =   40
  187.       TabIndex        =   9
  188.       Top             =   1620
  189.       Width           =   4215
  190.    End
  191.    Begin VB.TextBox txtData 
  192.       DataField       =   "ADDRESS1"
  193.       DataSource      =   "Data1"
  194.       Height          =   315
  195.       Index           =   3
  196.       Left            =   1380
  197.       MaxLength       =   49
  198.       TabIndex        =   7
  199.       Top             =   1140
  200.       Width           =   4215
  201.    End
  202.    Begin VB.TextBox txtData 
  203.       DataField       =   "CUSTNUM"
  204.       DataSource      =   "Data1"
  205.       Height          =   285
  206.       Index           =   0
  207.       Left            =   1965
  208.       MaxLength       =   5
  209.       TabIndex        =   1
  210.       Top             =   210
  211.       Width           =   690
  212.    End
  213.    Begin VB.TextBox txtData 
  214.       DataField       =   "FIRSTNAME"
  215.       DataSource      =   "Data1"
  216.       Height          =   315
  217.       Index           =   2
  218.       Left            =   5280
  219.       MaxLength       =   20
  220.       TabIndex        =   5
  221.       Top             =   660
  222.       Width           =   2595
  223.    End
  224.    Begin VB.TextBox txtData 
  225.       DataField       =   "LASTNAME"
  226.       DataSource      =   "Data1"
  227.       Height          =   315
  228.       Index           =   1
  229.       Left            =   1380
  230.       MaxLength       =   20
  231.       TabIndex        =   3
  232.       Top             =   660
  233.       Width           =   2595
  234.    End
  235.    Begin VB.Label lblFax 
  236.       AutoSize        =   -1  'True
  237.       BackColor       =   &H00C0C0C0&
  238.       Caption         =   "Fa&x:"
  239.       Height          =   195
  240.       Left            =   3420
  241.       TabIndex        =   18
  242.       Top             =   2640
  243.       Width           =   375
  244.    End
  245.    Begin VB.Label lblPhone 
  246.       AutoSize        =   -1  'True
  247.       BackColor       =   &H00C0C0C0&
  248.       Caption         =   "&Phone:"
  249.       Height          =   195
  250.       Left            =   660
  251.       TabIndex        =   16
  252.       Top             =   2640
  253.       Width           =   615
  254.    End
  255.    Begin VB.Label Label3 
  256.       AutoSize        =   -1  'True
  257.       BackColor       =   &H00C0C0C0&
  258.       Caption         =   "&Zip Code:"
  259.       Height          =   195
  260.       Left            =   5415
  261.       TabIndex        =   14
  262.       Top             =   2160
  263.       Width           =   840
  264.    End
  265.    Begin VB.Label Label2 
  266.       AutoSize        =   -1  'True
  267.       BackColor       =   &H00C0C0C0&
  268.       Caption         =   "S&tate:"
  269.       Height          =   195
  270.       Left            =   4170
  271.       TabIndex        =   12
  272.       Top             =   2160
  273.       Width           =   525
  274.    End
  275.    Begin VB.Label Label1 
  276.       AutoSize        =   -1  'True
  277.       BackColor       =   &H00C0C0C0&
  278.       Caption         =   "&City:"
  279.       Height          =   195
  280.       Left            =   885
  281.       TabIndex        =   10
  282.       Top             =   2160
  283.       Width           =   390
  284.    End
  285.    Begin VB.Label lblAddress2 
  286.       AutoSize        =   -1  'True
  287.       BackColor       =   &H00C0C0C0&
  288.       Caption         =   "Addre&ss 2:"
  289.       Height          =   195
  290.       Left            =   360
  291.       TabIndex        =   8
  292.       Top             =   1680
  293.       Width           =   915
  294.    End
  295.    Begin VB.Label lblAddress1 
  296.       AutoSize        =   -1  'True
  297.       BackColor       =   &H00C0C0C0&
  298.       Caption         =   "Addr&ess 1:"
  299.       Height          =   195
  300.       Left            =   360
  301.       TabIndex        =   6
  302.       Top             =   1200
  303.       Width           =   915
  304.    End
  305.    Begin VB.Label lblCustomerNumber 
  306.       AutoSize        =   -1  'True
  307.       BackColor       =   &H00C0C0C0&
  308.       Caption         =   "Customer &Number:"
  309.       Height          =   195
  310.       Left            =   300
  311.       TabIndex        =   0
  312.       Top             =   240
  313.       Width           =   1560
  314.    End
  315.    Begin VB.Label lblFirst 
  316.       AutoSize        =   -1  'True
  317.       BackColor       =   &H00C0C0C0&
  318.       Caption         =   "&First Name:"
  319.       Height          =   195
  320.       Left            =   4200
  321.       TabIndex        =   4
  322.       Top             =   720
  323.       Width           =   975
  324.    End
  325.    Begin VB.Label lblLast 
  326.       AutoSize        =   -1  'True
  327.       BackColor       =   &H00C0C0C0&
  328.       Caption         =   "&Last Name:"
  329.       Height          =   195
  330.       Left            =   300
  331.       TabIndex        =   2
  332.       Top             =   720
  333.       Width           =   975
  334.    End
  335.    Begin VB.Menu mnuFile 
  336.       Caption         =   "&File"
  337.       Begin VB.Menu mnuFilePrint 
  338.          Caption         =   "&Print"
  339.       End
  340.       Begin VB.Menu mnuFileSep 
  341.          Caption         =   "-"
  342.       End
  343.       Begin VB.Menu mnuFileExit 
  344.          Caption         =   "E&xit"
  345.          Shortcut        =   ^Q
  346.       End
  347.    End
  348.    Begin VB.Menu mnuSeek 
  349.       Caption         =   "&Seek..."
  350.    End
  351.    Begin VB.Menu mnuIndex 
  352.       Caption         =   "&Index"
  353.       Begin VB.Menu mnuIndexCustomerNumber 
  354.          Caption         =   "&Customer Number"
  355.       End
  356.       Begin VB.Menu mnuIndexName 
  357.          Caption         =   "&Name"
  358.       End
  359.       Begin VB.Menu mnuIndexState 
  360.          Caption         =   "&State"
  361.       End
  362.       Begin VB.Menu mnuIndexZipCode 
  363.          Caption         =   "&Zip Code"
  364.       End
  365.       Begin VB.Menu mnuIndexSep1 
  366.          Caption         =   "-"
  367.       End
  368.       Begin VB.Menu mnuIndexNaturalOrder 
  369.          Caption         =   "Natural &Order"
  370.       End
  371.       Begin VB.Menu mnuIndexSep2 
  372.          Caption         =   "-"
  373.       End
  374.       Begin VB.Menu mnuIndexListindexes 
  375.          Caption         =   "&List Indexes"
  376.       End
  377.    End
  378. End
  379. Attribute VB_Name = "frmCustomers"
  380. Attribute VB_Creatable = False
  381. Attribute VB_Exposed = False
  382. Option Explicit
  383.  
  384. ' DataChanged is used to keep track of whether a form needs to be saved.
  385. ' It is set at false by the first call to DisplayRecord. All text box Change
  386. ' events set it true. When a record is saved or a new record is displayed,
  387. ' it is reset back to false.
  388.  
  389. Private DataChanged As Boolean
  390.  
  391. ' db is the database variable, declared at form level. It is Set to
  392. ' the correct directory in the Form Load event.
  393.  
  394. Private db As DATABASE
  395.  
  396. ' rs is the customer recordset. It is Set to the CUSTOMER.DBF
  397. ' table in the Form_Load event.
  398.  
  399. Private rs As Recordset
  400.  
  401. ' We use a control array for the text boxes. The following constants are
  402. ' used to make the array index numbers meaningful.
  403.  
  404. Private Const CUSTNUM = 0
  405. Private Const LASTNAME = 1
  406. Private Const FIRSTNAME = 2
  407. Private Const ADDRESS1 = 3
  408. Private Const ADDRESS2 = 4
  409. Private Const CITY = 5
  410. Private Const STATE = 6
  411. Private Const ZIPCODE = 7
  412. Private Const PHONE = 8
  413. Private Const FAX = 9
  414. Private Sub Form_Load()
  415.     Dim dbName As String
  416.     
  417.     ' Set the two data access object variables that were declared at
  418.     ' module level.
  419.  
  420.     ' Get the database name and open the database.
  421.     dbName = DataPath() & "\CHAPTER.05" ' DataPath() is in READINI.BAS
  422.     Set db = DBEngine.Workspaces(0).OpenDatabase _
  423.      (dbName, False, False, "dBase IV;")
  424.  
  425.     Set rs = db.OpenRecordset("CUSTOMER", dbOpenTable)
  426.  
  427.     UpdateMenuStatus "NATURAL"
  428.  
  429. End Sub
  430.  
  431. Private Sub Form_Activate()
  432.  
  433.     ' If there are no records in the table, then both beginning-of-file (BOF)
  434.     ' and end-of-file (EOF) are True. If this is true, call EmptyRecordset,
  435.     ' which gives the user a choice between adding a new blank record and
  436.     ' terminating the program.
  437.  
  438.     If rs.BOF And rs.EOF Then EmptyRecordset
  439.  
  440.     ' Display the first record in the table recordset.
  441.  
  442.     DisplayRecord
  443.     
  444. End Sub
  445.  
  446. Private Sub cmdAdd_Click()
  447.  
  448.     ' The user clicked the Add button.
  449.     
  450.     Dim currentIndex As String
  451.     
  452.     ' Store the current index method and then turn on Natural Order.
  453.     ' This is necessary to display the new blank record as soon as it's been
  454.     ' added, because adding the record does not automatically point the
  455.     ' record pointer at it, and when an index is active the position of the
  456.     ' new record will be unpredictable. When no index is active, the new
  457.     ' record will always be at the end of the record set.
  458.     
  459.     currentIndex = GetCurrentIndexState()
  460.     
  461.     ' Use the menu click event to change to natural order (i.e., no index).
  462.     
  463.     mnuIndexNaturalOrder_Click
  464.  
  465.     With rs
  466.  
  467.         ' Prepare to add a new blank record.
  468.  
  469.         .AddNew
  470.     
  471.         ' Now actually add the record.
  472.     
  473.          .UPDATE
  474.  
  475.         ' Move to the new record
  476.     
  477.        .MoveLast
  478.  
  479.     End With
  480.  
  481.     ' Restore the index that was in effect at the beginning of the procedure.
  482.  
  483.     Select Case currentIndex
  484.  
  485.         ' If no index was in effect, just display the current record.
  486.         ' Otherwise, reset the index with the appropriate menu click routine.
  487.         ' The menu click routine takes care of setting the record pointer back to the
  488.         ' newly created record and refreshing the form.
  489.  
  490.         Case "NATURAL"
  491.             DisplayRecord
  492.         Case "CUSTNUM"
  493.             mnuIndexCustomerNumber_Click
  494.         Case "NAME"
  495.             mnuIndexName_Click
  496.         Case "STATE"
  497.             mnuIndexState_Click
  498.         Case "ZIPCODE"
  499.              mnuIndexZipCode_Click
  500.    End Select
  501.    
  502.    ' Display the new record for user entry.
  503.     
  504.     DisplayRecord
  505.  
  506. End Sub
  507.  
  508. Private Sub cmdDelete_Click()
  509.  
  510.     ' Get confirmation that the user wants to delete the current record.
  511.  
  512.    If MsgBox("Do you want to delete " & MakeName(CStr(txtData(LASTNAME)), _
  513.    CStr(txtData(FIRSTNAME))) & "?", vbQuestion + vbYesNo + vbDefaultButton2) _
  514.     = vbYes Then
  515.  
  516.         ' Delete the record
  517.         ' To remove the record from the active set, the line "Deleted=On"
  518.         ' must appear in the [dBase ISAM] section of VB.INI or the
  519.         ' application's INI file. See How-To 4.1 for details.
  520.  
  521.         ' If the user deleted the only record in the database, call the
  522.         ' EmptyRecordset procedure to give the user a chance to add a new
  523.         ' blank record. If the user chooses not to add a new record,
  524.         ' EmptyRecordset terminates the program.
  525.  
  526.         rs.DELETE
  527.  
  528.         ' If the user deleted the only record in the database, call the
  529.         ' EmptyRecordset procedure to give the user a chance to add a new
  530.         ' blank record. If the user chooses not to add a new record,
  531.         ' EmptyRecordset terminates the program.
  532.  
  533.         If rs.BOF And rs.EOF Then
  534.             EmptyRecordset
  535.  
  536.         Else
  537.  
  538.             ' After a delete, the recordset has no current record. So move
  539.             ' to the next record in the recordset.
  540.  
  541.             rs.MoveNext
  542.  
  543.             ' If the user deleted the record that was positioned
  544.             ' at the end of the database, move to the previous record. Since
  545.             ' we checked earlier for an empty database, we know there must
  546.             ' a previous record.
  547.  
  548.             If rs.EOF Then rs.MovePrevious
  549.  
  550.             ' Display the new current record.
  551.  
  552.             DisplayRecord
  553.  
  554.         End If
  555.  
  556.     End If
  557.  
  558. End Sub
  559.  
  560. Private Sub cmdClose_Click()
  561.  
  562.     Unload frmCustomers
  563.     
  564. End Sub
  565.  
  566. Private Sub cmdMove_Click(Index As Integer)
  567.     
  568.     ' The user clicked one of the navigation buttons - First, Prev, Next, or
  569.     ' Last. Since these buttons are a control array, the specific button
  570.     ' clicked is passed in the Index argument.
  571.     
  572.     Dim performMove As Integer
  573.     Const MOVE_FIRST = 0
  574.     Const MOVE_PREVIOUS = 1
  575.     Const MOVE_NEXT = 2
  576.     Const MOVE_LAST = 3
  577.     
  578.     ' Set the performMove flag to its default value
  579.     
  580.     performMove = True
  581.     
  582.     ' If the data have changed since the last time the record was saved, save
  583.     ' the record. If the save is successful, performMove will remain True;
  584.     ' otherwise, it will be set to False.
  585.     
  586.     If DataChanged Then performMove = SaveRecord()
  587.     
  588.     ' If the data have not changed or the save operation was successful, then
  589.     ' change to the specified record.
  590.     
  591.     If performMove = True Then
  592.         Select Case Index
  593.             Case MOVE_NEXT
  594.                 
  595.                 ' Check to make sure the record pointer's not at EOF. Without
  596.                 ' this, an error would occur if the pointer was at EOF.
  597.                 
  598.                 If Not rs.EOF Then
  599.                     
  600.                     ' Okay to move to the next record.
  601.                     
  602.                     rs.MoveNext
  603.                     
  604.                     ' Now did the move put the pointer at EOF? If so, there's
  605.                     ' no current record, and several other routines assume
  606.                     ' there's always a current record. So if the pointer's at
  607.                     ' EOF, move it back to where it was.
  608.                     
  609.                     If rs.EOF Then rs.MovePrevious
  610.                 End If
  611.             Case MOVE_PREVIOUS
  612.                 
  613.                 ' Check to make sure the record pointer's not at BOF. Without
  614.                 ' this, an error would occur if the pointer was at BOF.
  615.                 
  616.                 If Not rs.BOF Then
  617.                     
  618.                     ' Okay to move to the previous record.
  619.                     
  620.                     rs.MovePrevious
  621.                     
  622.                     ' Now did the move put the pointer at BOF? If so, there's
  623.                     ' no current record, and several other routines assume
  624.                     ' there's always a current record. So if the pointer's at
  625.                     ' BOF, move it back to where it was.
  626.                     
  627.                     If rs.BOF Then rs.MoveNext
  628.                 End If
  629.             Case MOVE_LAST
  630.                 
  631.                 ' Move the record pointer to the last record in the file.
  632.                 
  633.                 rs.MoveLast
  634.             Case MOVE_FIRST
  635.                 
  636.                 ' Move the record pointer to the first record in the file.
  637.                 
  638.                 rs.MoveFirst
  639.         End Select
  640.         
  641.         ' Show the record the record pointer's currently pointing at.
  642.         
  643.         DisplayRecord
  644.     End If
  645. End Sub
  646.  
  647. Sub EmptyRecordset()
  648.  
  649.     ' Gives the user a chance to add a record to the data base. If the user
  650.     ' elects not to add a record, the program terminates.
  651.  
  652.     Dim msg1 As String, msg2 As String, msg3 As String
  653.        
  654.     msg1 = "There are no customer records in the data base. "
  655.     msg2 = "Do you want to add a new blank record? "
  656.     msg3 = "(If you answer no, the program will terminate.)"
  657.     If MsgBox(msg1 & msg2 & msg3, vbQuestion + vbYesNo) = vbYes Then
  658.         cmdAdd_Click
  659.     Else
  660.         End
  661.     End If
  662.  
  663. End Sub
  664.  
  665. Private Function MakeName(LASTNAME As String, FIRSTNAME As String) As String
  666.  
  667.     ' Returns a name of the form First Last, compensating for the
  668.     ' possibility that either first or last name may be a zero-length string.
  669.  
  670.     Dim nm As String
  671.     
  672.     nm = FIRSTNAME & IIf(FIRSTNAME <> "", " ", "") & LASTNAME
  673.     MakeName = IIf(nm = "", "the current record", nm)
  674.     
  675. End Function
  676.  
  677. Private Sub DisplayField(txt As TextBox, fieldName As String)
  678.  
  679.     ' If fieldName is not null, displays the contents of the field in the
  680.     ' text box. If the field is null, displays an empty string.
  681.  
  682.     txt = IIf(Not IsNull(rs(fieldName)), rs(fieldName), "")
  683.  
  684. End Sub
  685.  
  686. Private Sub DisplayRecord()
  687.  
  688.     ' This procdeure displays the current record by calling DisplayField for
  689.     ' for each text box control on the form.
  690.  
  691.     DisplayField txtData(CUSTNUM), "CUSTNUM"
  692.     DisplayField txtData(LASTNAME), "LASTNAME"
  693.     DisplayField txtData(FIRSTNAME), "FIRSTNAME"
  694.     DisplayField txtData(ADDRESS1), "ADDRESS1"
  695.     DisplayField txtData(ADDRESS2), "ADDRESS2"
  696.     DisplayField txtData(CITY), "CITY"
  697.     DisplayField txtData(STATE), "STATE"
  698.     DisplayField txtData(ZIPCODE), "ZIPCODE"
  699.     DisplayField txtData(PHONE), "PHONE"
  700.     DisplayField txtData(FAX), "FAX"
  701.     
  702.     txtData(CUSTNUM).SetFocus
  703.     
  704.     ' DataChanged is set to true by the Change event of every text box
  705.     ' which fires in every DisplayField routine. Set it false now because
  706.     ' the data have not changed since the last save.
  707.     
  708.     DataChanged = False
  709. End Sub
  710.  
  711. Private Function SaveRecord()
  712.  
  713.     ' This procedure saves the current record to he data base file. If it is
  714.     ' successful, it returns True. If an error occurs, it returns False.
  715.  
  716.     On Error GoTo SaveRecordError
  717.  
  718.     With rs
  719.  
  720.         ' Move the record into the edit buffer.
  721.  
  722.         .Edit
  723.  
  724.         ' Now set the data fields from the text boxes on the form.
  725.  
  726.         !CUSTNUM = txtData(CUSTNUM)
  727.         !LASTNAME = txtData(LASTNAME)
  728.         !FIRSTNAME = txtData(FIRSTNAME)
  729.         !ADDRESS1 = txtData(ADDRESS1)
  730.         !ADDRESS2 = txtData(ADDRESS2)
  731.         !CITY = txtData(CITY)
  732.         !STATE = UCase$(txtData(STATE))
  733.         !ZIPCODE = txtData(ZIPCODE)
  734.         !PHONE = txtData(PHONE)
  735.         !FAX = txtData(FAX)
  736.  
  737.         ' Now update the data base. If you forget this step you'll accomplish
  738.         ' nothing - and no error message to warn you! If an error occurs
  739.         ' before this step is reached, the data will not be saved, since the
  740.         ' error-handling routine exits from the function.
  741.  
  742.          .UPDATE
  743.  
  744.     End With
  745.  
  746.     ' Set the module-level variable DataChanged to false.
  747.  
  748.     DataChanged = False
  749.  
  750.     ' Return True to indicated that the data were saved successfully.
  751.  
  752.     SaveRecord = True
  753.  
  754. Exit Function
  755.  
  756. SaveRecordError:
  757.  
  758.     ' If an error code 13 (Type Mismatch) caused the error, the error must be
  759.     ' in the Customer Number field which requires a numeric value (all the
  760.     ' other text boxes are saved to text fields and they will take anything),
  761.     ' so display a meaningful error message.
  762.  
  763.     If Err = 13 Then
  764.         MsgBox "The Customer Number field must contain a numeric value.", _
  765.         vbExclamation
  766.         txtData(CUSTNUM).SetFocus
  767.     Else
  768.  
  769.         ' Not error 13, so just pass through Visual Basic's error message.
  770.  
  771.         MsgBox Error(Err)
  772.     End If
  773.  
  774.     ' Return False to indicated that the data were not saved successfully.
  775.  
  776.     SaveRecord = False
  777.  
  778. Exit Function
  779.  
  780. End Function
  781.  
  782. Private Sub txtData_Change(Index As Integer)
  783.     DataChanged = True
  784. End Sub
  785.  
  786. Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
  787.  
  788.     ' This event is evoked automatically before the program is unloaded.
  789.     ' If the UnloadMode argument indicates that the cause of the unload
  790.     ' request is from the Windows Task Manager's End Task command or from a
  791.     ' command to exit from Windows, then the procedure calls ExitProgram().
  792.     ' If the current record need not be saved or if the current record is
  793.     ' saved without error, ExitProgram() simply Ends; otherwise, it returns
  794.     ' False. The False is converted to a True, which is returned to the
  795.     ' calling program by assigning it to the Cancel argument. Since setting
  796.     ' Cancel to any non-zero value cancels the event, this prevents the
  797.     ' program from being terminated.
  798.  
  799.     ' If the cause of the Unload query is the user choosing Close or closing
  800.     ' through the Control menu, ExitProgram() is called from the Form_Unload
  801.     ' or mnuFileExit_Click procedure, so there's no need to duplicate the call
  802.     ' here.
  803.  
  804.     Const TASKMANAGER = 2
  805.     Const EXITWINDOWS = 3
  806.  
  807.     If UnloadMode = TASKMANAGER Or UnloadMode = EXITWINDOWS Then
  808.         Cancel = Not ExitProgram()
  809.     End If
  810. End Sub
  811.  
  812. Private Sub Form_Unload(Cancel As Integer)
  813.     
  814.     ' Calls the ExitProgram routine, which saves the current record if it's
  815.     ' been changed, then executes an End statement.
  816.     
  817.     If ExitProgram() = False Then Cancel = True
  818. End Sub
  819.  
  820. Private Sub mnuFileExit_Click()
  821.  
  822.     ' The user clicked Exit on the File menu or pressed Ctrl-Q.
  823.  
  824.     ' Calls the ExitProgram routine which saves the current record if it's
  825.     ' been changed, then executes an End statement. If the save fails,
  826.     ' ExitProgram does not execute the End, but instead returns a False.
  827.     ' This procedure just ignores the return value and does nothing if
  828.     ' the program cannot exit.
  829.  
  830.     ExitProgram
  831.  
  832. End Sub
  833.  
  834. Private Function ExitProgram() As Boolean
  835.     
  836.     ' This routine is called from the mnuFileExit_Click event and from the
  837.     ' Form_Unload event. This gives the application consistent behavior no
  838.     ' matter how the user exits from the program. If the current record does
  839.     ' not need saving or if it's saved successfully, the function Ends the
  840.     ' program. If the current record is not saved successfully, the function
  841.     ' returns a False.
  842.     
  843.     If DataChanged Then
  844.         If SaveRecord() = True Then
  845.             End
  846.         Else
  847.             ExitProgram = False
  848.         End If
  849.     Else
  850.         End
  851.     End If
  852. End Function
  853.  
  854. Private Function GetCurrentIndexState() As String
  855.  
  856.     ' This function returns the name of the currently active index.
  857.     ' It determines the index by seeing which Index menu item is checked.
  858.  
  859.     If mnuIndexCustomerNumber.Checked Then
  860.         GetCurrentIndexState = "CUSTNUM"
  861.     ElseIf mnuIndexState.Checked Then
  862.         GetCurrentIndexState = "STATE"
  863.     ElseIf mnuIndexZipCode.Checked Then
  864.         GetCurrentIndexState = "ZIPCODE"
  865.     ElseIf mnuIndexName.Checked Then
  866.         GetCurrentIndexState = "NAME"
  867.     Else
  868.         GetCurrentIndexState = "NATURAL"
  869.     End If
  870. End Function
  871.  
  872. Private Sub mnuFilePrint_Click()
  873.  
  874.     ' This procedure dumps the current database to the default Windows printer.
  875.     ' If an index is active, the printout is sorted by the index.
  876.  
  877.     ' The currentRecord variable is used to hold the bookmark position.
  878.  
  879.     Dim currentRecord As Variant
  880.  
  881.     ' These constants are used to set the printer margins. They are in twips
  882.     ' (1 twip = 1/LEFT_MARGIN in.). The values shown will give an LaserJet
  883.     ' printer 1" margins. Change them to suit your preferences.
  884.  
  885.     Const LEFT_MARGIN = 1080
  886.     Const TOP_MARGIN = 1080
  887.  
  888.     On Error GoTo PrintError
  889.  
  890.     ' Verify that the database supports bookmarks. If it does, bookmark the
  891.     ' current record so that it can be restored as the active record after
  892.     ' the print job has been sent to the Print Manager.
  893.  
  894.     If rs.Bookmarkable Then
  895.         currentRecord = rs.Bookmark
  896.     End If
  897.  
  898.     ' Show the hourglass.
  899.  
  900.     Screen.MousePointer = 11
  901.  
  902.     ' Set the top margin.
  903.  
  904.     Printer.CurrentY = TOP_MARGIN
  905.  
  906.     ' Go to the first record. Cycle through all the records until the end of
  907.     ' the file is reached.
  908.  
  909.     rs.MoveFirst
  910.     Do While Not rs.EOF
  911.  
  912.         ' Print the customer number at the left margin. The prompt gets printed
  913.         ' whether or not there's anything in the field.
  914.  
  915.         Printer.CurrentX = LEFT_MARGIN
  916.         Printer.Print "Customer Number: " & IIf(IsNull(rs("CUSTNUM")), "", _
  917.          Format$(rs("CUSTNUM")))
  918.  
  919.         ' Print Lastname, Firstname at the left margin.
  920.  
  921.         Printer.CurrentX = LEFT_MARGIN
  922.         If Not IsNull(rs("LASTNAME")) Then Printer.Print rs("LASTNAME") & ", ";
  923.         Printer.Print IIf(IsNull(rs("FIRSTNAME")), "", rs("FIRSTNAME"))
  924.         Printer.CurrentX = LEFT_MARGIN
  925.  
  926.         ' If there's an Address1, print it at the left margin.
  927.  
  928.         If Not IsNull(rs("ADDRESS1")) Then Printer.Print rs("ADDRESS1")
  929.         Printer.CurrentX = LEFT_MARGIN
  930.  
  931.         ' If there's an Address2, print it at the left margin.
  932.  
  933.         If Not IsNull(rs("ADDRESS2")) Then Printer.Print rs("ADDRESS2")
  934.         Printer.CurrentX = LEFT_MARGIN
  935.  
  936.         ' Print City, State Zip at the left margin.
  937.  
  938.         If Not IsNull(rs("CITY")) Then Printer.Print rs("CITY") & ", ";
  939.         If Not IsNull(rs("STATE")) Then Printer.Print rs("STATE") & " ";
  940.         Printer.Print IIf(IsNull(rs("ZIPCODE")), "", rs("ZIPCODE"))
  941.         Printer.CurrentX = LEFT_MARGIN
  942.  
  943.         ' If there's a phone number, print it at the left margin.
  944.  
  945.         If Not IsNull(rs("PHONE")) Then Printer.Print "Phone: " & rs("PHONE")
  946.         Printer.CurrentX = LEFT_MARGIN
  947.  
  948.         ' If there's a fax number, print it at the left margin.
  949.  
  950.         If Not IsNull(rs("FAX")) Then Printer.Print "Fax: " & rs("FAX")
  951.  
  952.         ' Insert a blank line.
  953.  
  954.         Printer.Print
  955.  
  956.         ' Move to the next record
  957.  
  958.         rs.MoveNext
  959.     Loop
  960.  
  961.     ' All done, so tell Print Manager to do its thing.
  962.  
  963.     Printer.EndDoc
  964.  
  965.     ' If a bookmark was set earlier, restore the bookmarked record. Otherwise,
  966.     ' display the first record in the data base.
  967.  
  968.     If rs.Bookmarkable Then
  969.         rs.Bookmark = currentRecord
  970.     Else
  971.         rs.MoveFirst
  972.     End If
  973.  
  974.     ' Restore the default mouse cursor.
  975.  
  976.     Screen.MousePointer = 0
  977.     
  978. Exit Sub
  979.  
  980. PrintError:
  981.  
  982.     MsgBox Error(Err)
  983.  
  984. Exit Sub
  985. End Sub
  986.  
  987. Private Sub ActivateIndex(whichIndex As String)
  988.  
  989.     ' This procedure is also called from the mnuIndex* routines to set
  990.     ' the designated index.
  991.  
  992.     Dim currentRecord As Variant
  993.     Dim performChange As Integer
  994.  
  995.     ' Initialize the performChange flag to True.
  996.  
  997.     performChange = True
  998.  
  999.     ' If the current record has been changed since the last save, save it.
  1000.     ' If the save is successful, then performChange remains True; otherwise,
  1001.     ' it is set to False. If performChange is True, go ahead and change the
  1002.     ' index.
  1003.  
  1004.     If DataChanged Then performChange = SaveRecord()
  1005.     If performChange = True Then
  1006.  
  1007.         ' If the database file type supports bookmarks, set a bookmark at the
  1008.         ' current record so that it can be restored as the current record
  1009.         ' after the index has been changed.
  1010.  
  1011.         If rs.Bookmarkable Then currentRecord = rs.Bookmark
  1012.  
  1013.         ' Set the index.
  1014.  
  1015.         rs.Index = whichIndex
  1016.  
  1017.         ' Check the menu item on the Index menu and enable the Seek menu.
  1018.  
  1019.         UpdateMenuStatus whichIndex
  1020.  
  1021.         ' If a bookmark was set earlier, use it to redisplay the same record.
  1022.  
  1023.         If rs.Bookmarkable Then rs.Bookmark = currentRecord
  1024.  
  1025.         ' Make sure the current record is the one displayed on the form.
  1026.  
  1027.         DisplayRecord
  1028.     End If
  1029. End Sub
  1030.  
  1031. Private Sub mnuIndexCustomerNumber_Click()
  1032.  
  1033.     ' The user chose the Customer Number selection from the index menu.
  1034.     ' This procedure is also called from the cmdAdd_Click routine to reset
  1035.     ' the index after a record has been added.
  1036.  
  1037.     ActivateIndex "CUSTNUM"
  1038.     
  1039. End Sub
  1040.  
  1041. Private Sub mnuIndexListIndexes_Click()
  1042.  
  1043.     ' This procedure displays a message box that lists all the indexes for
  1044.     ' the current database along with the fields in each index.
  1045.  
  1046.     Dim numIndexes As Integer
  1047.     Dim currentIndex As Integer
  1048.     Dim indexList As String
  1049.  
  1050.     ' Use the Count property of the Indexes collection of the recordset
  1051.     ' to find the number of indexes in the collection.
  1052.  
  1053.     numIndexes = rs.Indexes.Count
  1054.  
  1055.     ' Make sure there's at least one index.
  1056.  
  1057.     If numIndexes > 0 Then
  1058.  
  1059.         ' Cycle through the indexes in the collection.
  1060.         ' The first index is numbered 0.
  1061.  
  1062.         For currentIndex = 0 To numIndexes - 1
  1063.  
  1064.             ' Build the indexList string by appending information about the
  1065.             ' current index to the current contents of the indexList variable.
  1066.             ' For each index, the string will show the index number, index
  1067.             ' name, and the fields that make up the index.
  1068.             ' Each index entry is followed by a CRLF combination.
  1069.  
  1070.             indexList = indexList & Format$(currentIndex) & ": " & _
  1071.              rs.Indexes(currentIndex).Name & " (" & _
  1072.              rs.Indexes(currentIndex).Fields & ")" & Chr$(13) & Chr$(10)
  1073.              
  1074.         Next currentIndex
  1075.  
  1076.         ' Display the index list in a standard message box.
  1077.  
  1078.         MsgBox indexList, vbInformation, "CUSTOMER Table Index List"
  1079.     End If
  1080.  
  1081. End Sub
  1082.  
  1083. Private Sub mnuIndexName_Click()
  1084.  
  1085.     ' The user chose the Name selection from the index menu.
  1086.     ' This procedure is also called from the cmdAdd_Click routine to reset
  1087.     ' the index after a record has been added.
  1088.  
  1089.     ActivateIndex "NAME"
  1090.     
  1091.  
  1092. End Sub
  1093.  
  1094. Private Sub mnuIndexNaturalOrder_Click()
  1095.  
  1096.     ' The user chose the Natural Order selection from the index menu.
  1097.     ' This procedure is also called from the cmdAdd_Click routine to turn off
  1098.     ' the index prior to adding a record.
  1099.  
  1100.     Dim currentRecord As Variant
  1101.     Dim performChange As Integer
  1102.  
  1103.     ' Initialize the performChange flag to True.
  1104.  
  1105.     performChange = True
  1106.  
  1107.     ' If the current record has been changed since the last save, save it.
  1108.     ' If the save is successful, then performChange remains True; otherwise,
  1109.     ' it is set to False.
  1110.     ' If performChange is True, go ahead and change the index.
  1111.  
  1112.     If DataChanged Then performChange = SaveRecord()
  1113.     If performChange = True Then
  1114.  
  1115.         ' If the database file type supports bookmarks, set a bookmark at the
  1116.         ' current record so that it can be restored
  1117.         ' as the current record after the index has been changed.
  1118.  
  1119.         If rs.Bookmarkable Then currentRecord = rs.Bookmark
  1120.  
  1121.         ' Set the record order to natural order by setting the index to an
  1122.         ' empty string.
  1123.  
  1124.         rs.Index = ""
  1125.  
  1126.         ' Check the Natural Order menu item on the Index menu and disable
  1127.         ' the Seek menu.
  1128.  
  1129.         UpdateMenuStatus "NATURAL"
  1130.  
  1131.         ' If a bookmark was set earlier, use it to redisplay the same record.
  1132.  
  1133.         If rs.Bookmarkable Then rs.Bookmark = currentRecord
  1134.  
  1135.         ' Make sure the current record is the one displayed on the form.
  1136.  
  1137.         DisplayRecord
  1138.     End If
  1139. End Sub
  1140.  
  1141. Private Sub mnuIndexState_Click()
  1142.  
  1143.     ' The user chose the State selection from the index menu.
  1144.     ' This procedure is also called from the cmdAdd_Click routine to reset the
  1145.     ' index after a record has been added.
  1146.  
  1147.     ActivateIndex "STATE"
  1148.     
  1149. End Sub
  1150.  
  1151. Private Sub mnuIndexZipCode_Click()
  1152.  
  1153.     ' The user chose the Zip Code selection from the index menu.
  1154.     ' This procedure is also called from the cmdAdd_Click routine to reset the
  1155.     ' index after a record has been added.
  1156.  
  1157.     ActivateIndex "ZIPCODE"
  1158.     
  1159. End Sub
  1160.  
  1161. Private Sub mnuSeek_Click()
  1162.     Dim seekWhat1 As String, seekWhat2 As String
  1163.     Dim currentIndex As String
  1164.  
  1165.     ' Find out what the currently active index is.
  1166.  
  1167.     currentIndex = GetCurrentIndexState()
  1168.  
  1169.     ' Get the value(s) from the user to be sought.
  1170.  
  1171.     If currentIndex = "CUSTNUM" Then
  1172.         seekWhat1 = InputBox$("Customer number to seek:", "Customer List")
  1173.     ElseIf currentIndex = "STATE" Then
  1174.         seekWhat1 = UCase$(InputBox$("State to seek:", "Customer List"))
  1175.     ElseIf currentIndex = "ZIPCODE" Then
  1176.         seekWhat1 = InputBox$("Zip Code to seek:", "Customer List")
  1177.         currentIndex = "ZIPCODE"
  1178.     Else
  1179.         seekWhat1 = InputBox$("Last name to seek:", "Customer List")
  1180.         seekWhat2 = InputBox$("First name to seek:", "Customer List")
  1181.         currentIndex = "NAME"
  1182.     End If
  1183.  
  1184.     ' Seek the requested record. The first argument to the Seek method is
  1185.     ' the type of comparison; in this case, it's an equality. The remaining
  1186.     ' arguments are the fields in the selected index.
  1187.  
  1188.     If currentIndex <> "NAME" Then
  1189.         rs.Seek "=", seekWhat1
  1190.     Else
  1191.         rs.Seek "=", seekWhat1, seekWhat2
  1192.     End If
  1193.  
  1194.     ' If the seek was successful, it points the record pointer to the first
  1195.     ' record matching the criteria. In this case, just refresh the form.
  1196.     ' If the seek was unsuccessful, inform the user.
  1197.  
  1198.     If Not rs.NoMatch Then
  1199.         DisplayRecord
  1200.     Else
  1201.         MsgBox "Record sought not found!", vbExclamation, "Customer List"
  1202.     End If
  1203.  
  1204. End Sub
  1205.  
  1206. Private Sub UpdateMenuStatus(ActiveIndex As String)
  1207.  
  1208.     ' This routine places a check mark beside the currently selected indexing
  1209.     ' method and enables/disables the Seek menu based on whether there is an
  1210.     ' index active or not. Other routines refer to the current check status
  1211.     ' of the menu to determine what index is active.
  1212.  
  1213.     ' Check the appropriate menu item based on the ActiveIndex argument. Uncheck all the others.
  1214.  
  1215.     mnuIndexCustomerNumber.Checked = IIf(ActiveIndex = "CUSTNUM", True, False)
  1216.     mnuIndexName.Checked = IIf(ActiveIndex = "NAME", True, False)
  1217.     mnuIndexZipCode.Checked = IIf(ActiveIndex = "ZIPCODE", True, False)
  1218.     mnuIndexState.Checked = IIf(ActiveIndex = "STATE", True, False)
  1219.     mnuIndexNaturalOrder.Checked = IIf(ActiveIndex = "NATURAL", True, False)
  1220.  
  1221.     ' If Natural Order is selected, it means no index is currently in effect.
  1222.     ' Since the Seek method requires an index to be active, gray the menu item
  1223.     ' if Natural Order is selected.
  1224.  
  1225.     mnuSeek.Enabled = Not mnuIndexNaturalOrder.Checked
  1226. End Sub
  1227.  
  1228.  
  1229.